
/* The program is to test stand alone AC-4
 * on randomly generated problems. 5 Feb 2004
 *
 * Test: ac4tesst.cpp
 * AC-4: ac4.cpp, ac4.h
 * CSP representation: csp.cpp, csp.h 
 * problem generator: urbcsp.cc
 * compiler: gcc -pg 
 *
 * this case needs long time to solve
 * a.out 50 50 150 1850 99 2
 */

#include "backtracking.h"
#include <errno.h>
#include <cstdio>

#include "resourcesUsageCounter.h"

// the parameters of a CSP: n # of var's; d size of domain; and 
// e the number of constraints

// used for the statistics
int num_consistent_instances[50]; 
int num_nonconsistent_instances[50]; 
int ncip = 0, nnip = 0;

// void consistent_instances(int, int, int);
// void nonconsistent_instances(int, int, int);

// to compute the average numbers
float average(float averageValue, int numOfValues, float newValue);
void random(int argc,char *argv[]);
void table(int argc,char *argv[]);
void domino(int argc,char *argv[]);

int main(int argc, char* argv[])
{
  if(argc <2)
  {
	  printf("System needs at least 1 input\n");
	  return 1;
  }
  if(argv[1][0]!='-')
  {
	  printf("First argument must be function switcher\n");
	  return 1;
  }
  switch(argv[1][1])
  {
  case 't':
	  table(argc,argv);
	  break;
  case 'r':
	  random(argc,argv);
	  break;
  case 'd':
	  domino(argc,argv);
	  break;
  default:
	  printf("Switch not recognized\n");
  }
  return 0;
}


void table(int argc,char *argv[])
{
  if (argc != 3)
    {
      printf("usage: filename\n");
      return;
    }
  
  ResourcesUsageCounter clock;


  cout << "Using table found in file " << argv[2] << endl;
  cout << "\nInstance " << 0 << ":\n";
  // the random instances    
  BT csp(argv[2]);
  //csp.printCSP();
  clock.start();
  if(csp.solve()){
    // printf("Instance %d is now arc consistent.\n", i);
    csp.checkSolution();
    //csp.printValueSelection();
  }
  else{
    // printf("Instance %d is not satisfied\n", i);
    // total_checks_nonconsistent += csp.checks();
    nnip++;
	cout << "CSP inconsistent, no answer set checking." << endl;
  }
  clock.stop();
  csp.statistics();
  cout << ':' << "Time used:" << clock << '\n';
  return;
}

void domino(int argc,char *argv[])
{
  int N, D, I;
  int n, d, e, i;
  if (argc != 5)
    {
      printf("usage: #vars #vals instances\n");
      return;
    }
     
  N = n = atoi(argv[2]);
  D = d = atoi(argv[3]);
  e = n;
  I = atoi(argv[4]);

  float averageCChecks = 0;
  float averageDChecks = 0;
  float averageBacktracks = 0;
  float averageMaxSearchDepth = 0;
  
  ResourcesUsageCounter clock, clock1;


  cout << "The parameters of the domino instances\n"
       << "  (n=" << n 	 
       << ", d="  << d << ", e=" << e << ", # of instances=" << I << ") \n";
  // cout << "#initial removed value:totally removed values:arc consistent(1)\n";
  for (i=0; i<I; ++i){

    cout << "\nInstance " << i << ":\n";

    // the random instances    
    BT csp(n, d);
    clock.start();

    clock1.reset();
    clock1.start();
    if(csp.solve()){
      // printf("Instance %d is now arc consistent.\n", i);
      num_consistent_instances[ncip] = i;
      // total_checks_consistent += csp.checks();
      ncip++;
	  csp.checkSolution();
	  //csp.printValueSelection();
    }
    else{
      // printf("Instance %d is not satisfied\n", i);
      num_nonconsistent_instances[nnip] = i;
      // total_checks_nonconsistent += csp.checks();
      nnip++;
	  cout << "CSP inconsistent, no answer set checking." << endl;
    }
    
    clock1.stop();
    clock.stop();
    csp.statistics();
    cout << ':' << "Time used:" << clock1 << '\n';
    averageCChecks = average(averageCChecks, i, csp.cchecks());
    averageDChecks = average(averageDChecks, i, csp.dchecks());
    averageBacktracks = average(averageBacktracks, i, 
				csp.getNumOfBacktracks());
    averageMaxSearchDepth = average(averageMaxSearchDepth, i, 
				    csp.getMaxSearchDepth());
  }

  std::cout << "average cchecks+dchecks: average backtracks: average search depth\n";
  std::cout << averageCChecks << '+' << averageDChecks 
	    << ':' << averageBacktracks << ':' 
	    << averageMaxSearchDepth << '\n'; 
    printf("the consistent instances are (%d) \n", ncip);
    for(i=0; i<ncip; i++) printf(" %d", num_consistent_instances[i]);
    printf("\n");
    printf("the inconsistent instances are (%d) \n", nnip);
    for(i=0; i<nnip; i++) printf(" %d", num_nonconsistent_instances[i]);
    printf("\n");
    std::cout << "Total time:" << clock << '\n';
  return;
}



void random(int argc,char *argv[])
{
  int N, D, C, T, I;
  int n, d, e,    i;
  int S, OS;
  if (argc != 8)
    {
      printf("usage: #vars #vals #constraints #nogoods seed instances\n");
      return;
    }
     
  n = N = atoi(argv[2]);
  d = D = atoi(argv[3]);
  e = C = atoi(argv[4]);
  T = atoi(argv[5]);
  OS = S = atoi(argv[6]);
  I = atoi(argv[7]);
  if (S > 0){
    S = -S;
    OS = -OS;
  } 

  float averageCChecks = 0;
  float averageDChecks = 0;
  float averageBacktracks = 0;
  float averageMaxSearchDepth = 0;
  
  ResourcesUsageCounter clock, clock1;


  cout << "The parameters of the random instances\n"
       << "  (n=" << n 	 
       << ", d="  << d << ", e=" << e << " , disallowed=" << T
       << ", # of instances=" << I << ", seed=" << -S << ") \n";
  // cout << "#initial removed value:totally removed values:arc consistent(1)\n";
  for (i=0; i<I; ++i){

	cout << "\nInstance " << i << ":" << endl;

    // the random instances    
    BT csp(n, d, e, T, &S);
    // Domino instances
    // BT csp(n, d, e);

    // time(&st);
     //csp.printVG();
    // if( i < I-1) continue; 
    clock.start();

    clock1.reset();
    clock1.start();
	if(csp.solve()){
      // printf("Instance %d is now arc consistent.\n", i);
      num_consistent_instances[ncip] = i;
      // total_checks_consistent += csp.checks();
      ncip++;
	  csp.checkSolution();
	  //csp.printValueSelection();
    }
    else{
      // printf("Instance %d is not satisfied\n", i);
      num_nonconsistent_instances[nnip] = i;
      // total_checks_nonconsistent += csp.checks();
      nnip++;
	  cout << "CSP inconsistent, no answer set checking." << endl;
    }
    
    clock1.stop();
    clock.stop();
    csp.statistics();
    cout << ':' << "Time used:" << clock1 << '\n';
    averageCChecks = average(averageCChecks, i, csp.cchecks());
    averageDChecks = average(averageDChecks, i, csp.dchecks());
    averageBacktracks = average(averageBacktracks, i, 
				csp.getNumOfBacktracks());
    averageMaxSearchDepth = average(averageMaxSearchDepth, i, 
				    csp.getMaxSearchDepth());
	//cout << "Finished with Instance " << i << endl;
	//getchar();
    // time(&et);
    // total_checks += num_checks;
    // printf("timing from %ld to %ld\n", st, et);
  }
/*
  if (ncip != 0){ 
    total_checks_consistent /= ncip; 
    consistent_instances(I, T, OS);
  }
  else total_checks_consistent = 0;
  if (nnip != 0){
    total_checks_nonconsistent /= nnip;
    nonconsistent_instances(I, T, OS);
  }
  else total_checks_nonconsistent = 0;
*/

  std::cout << "average cchecks+dchecks: average backtracks: average search depth\n";
  std::cout << averageCChecks << '+' << averageDChecks 
	    << ':' << averageBacktracks << ':' 
	    << averageMaxSearchDepth << '\n'; 
    printf("the consistent instances are (%d) \n", ncip);
    for(i=0; i<ncip; i++) printf(" %d", num_consistent_instances[i]);
    printf("\n");
    printf("the inconsistent instances are (%d) \n", nnip);
    for(i=0; i<nnip; i++) printf(" %d", num_nonconsistent_instances[i]);
    printf("\n");
    //  printf("the average checks for nonconsistent is %d (%d) \n", total_checks_nonconsistent, nnip);
    std::cout << "Total time:" << clock << '\n';
  return;
}

float average(float averageValue, int numOfValues, float newValue){
  float temp;
  
  temp = (float)averageValue/(numOfValues+1)*numOfValues + 
    (float) newValue/(numOfValues + 1);
  return temp; 
}
